home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 003 / roff / tpr0.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  11KB  |  547 lines

  1. /*
  2. **    tpr - text formatter
  3. **        Ken Yap, June 1981
  4. */
  5. #include    "tpr.h"
  6.  
  7. struct macro macros[MAXMAC];
  8. short maccnt    = 0;        /* counter for current macro */
  9. char *pbptr[MAXMAC];        /* pointers to pushed back lines */
  10. short pblev    = 0;        /* indicates level of macro nesting during collection */
  11.  
  12. char outbuf[MAXOUT];    /* lines to be filled collect here */
  13. char *outp    = outbuf;    /* last char position in outbuf; init = 0 */
  14. short outw    = 0;    /* width of text currenty in outbuf; init = 0 */
  15. short outwds    = 0;    /* number of words in outbuf; init = 0 */
  16.  
  17. short pages    = 1;    /* pages between pauses with -s option */
  18. short pausecount= 0;    /* decremented every page */
  19. short curpag    = 0;
  20. short newpag    = 1;
  21. short lineno    = 0;
  22. short peekno    = 1;
  23. short indline    = 0;
  24. short respage    = 0;
  25. char trapmac[2]    = "";
  26. char blnkhdr[]    = "\n";
  27. struct envir env    = {
  28.     PAGLEN, M1DEF, M2DEF, M3DEF, M4DEF, (PAGLEN-M3DEF-M4DEF),
  29.     blnkhdr, blnkhdr,
  30.     blnkhdr, blnkhdr,
  31.     '.', '\t', ' ',
  32.     YES, YES, ARABIC, 1, PAGEWIDTH, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  33.     { 8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,0 },
  34.     NULL
  35.     };
  36. struct envir *curenv    = NULL;
  37. struct cmdents builtins[] ={
  38.     { "ad",YES },
  39.     { "ar",YES },
  40.     { "bd",YES },
  41.     { "bl",YES },
  42.     { "bp",YES },
  43.     { "br",YES },
  44.     { "cc",YES },
  45.     { "ce",YES },
  46.     { "de",YES },
  47.     { "ef",YES },
  48.     { "eg",YES },
  49.     { "eh",YES },
  50.     { "fi",YES },
  51.     { "fo",YES },
  52.     { "he",YES },
  53.     { "in",YES },
  54.     { "ix",YES },
  55.     { "li",YES },
  56.     { "ll",YES },
  57.     { "ls",YES },
  58.     { "m1",YES },
  59.     { "m2",YES },
  60.     { "m3",YES },
  61.     { "m4",YES },
  62.     { "na",YES },
  63.     { "ne",YES },
  64.     { "nf",YES },
  65.     { "of",YES },
  66.     { "oh",YES },
  67.     { "pl",YES },
  68.     { "po",YES },
  69.     { "pt",YES },
  70.     { "re",YES },
  71.     { "rf",YES },
  72.     { "ro",YES },
  73.     { "rp",YES },
  74.     { "se",YES },
  75.     { "sk",YES },
  76.     { "so",YES },
  77.     { "sp",YES },
  78.     { "ta",YES },
  79.     { "tc",YES },
  80.     { "ti",YES },
  81.     { "ub",YES },
  82.     { "ul",YES }
  83.     };
  84.  
  85. short echodir    = 0;
  86. char *progname;
  87. char *filename    = "stdin";
  88. short fileline    = 0;
  89. short ttyfd    = -1;    /* for pause between pages */
  90. FILE *indfp    = NULL;
  91. char *nomem    = "Out of dynamic memory\n";    /* canned message */
  92.  
  93. /*
  94. **    main
  95. */
  96. main(argc,argv)
  97.     short argc;
  98.     char **argv;{
  99.     FILE *file;
  100. #ifdef unix
  101.     extern char _sobuf[];
  102. #endif
  103.     
  104.     progname = *argv;
  105.     for(argc--, argv++; argc > 0 && **argv == '-' && (*argv)[1] != '\0'; argc--, argv++)
  106.         setoptions(*argv);
  107. #ifdef unix
  108.     setbuf(stdout,_sobuf);
  109. #endif
  110.     if(argc == 0)
  111.         tpr(stdin,"stdin");
  112.     else
  113.         for( ; argc > 0; argc--, argv++){
  114.             if(**argv == '-' && (*argv)[1] == '\0')
  115.                 tpr(stdin,"stdin");
  116.             else{
  117.                 if((file = fopen(*argv,"r")) == NULL){
  118.                     perror(*argv);
  119.                     continue;
  120.                     }
  121.                 tpr(file,*argv);
  122.                 fclose(file);
  123.                 }
  124.             }
  125.     if(lineno > 0)
  126.         spc(HUGE);        /* flush last output */
  127.     if(indfp != NULL)
  128.         fclose(indfp);
  129.     fflush(stdout);
  130. }
  131.  
  132. setoptions(arg)
  133.     char *arg;{
  134.     register char c;
  135.     int isatty(),open();
  136.     FILE *fopen();
  137.  
  138.     while((c = *++arg) != '\0')
  139.         switch(c){
  140.             case 'd':    /* echo directives */
  141.                 echodir++;
  142.                 break;
  143.             case 'e':    /* divert errors */
  144.                 close(2);
  145.                 if(creat(++arg,0600) < 0){
  146.                     open("/dev/tty",1);
  147.                     perror(arg);
  148.                     exit(1);
  149.                     }
  150.                 return;
  151.             case 'i':    /* open index file */
  152.                 if((indfp = fopen(arg[1] == '\0' ? "index" : ++arg, "w")) == NULL)
  153.                     perror(arg);
  154.                 return;
  155.             case 'n':    /* set initial page number */
  156.                 curpag = atoi(++arg);
  157.                 if(curpag < 0)
  158.                     curpag = 0;
  159.                 newpag = curpag;
  160.                 return;
  161.             case 's':    /* pause every n pages */
  162.                 pages = atoi(++arg);
  163.                 if(pages <= 0)
  164.                     pages = 1;
  165.                 pausecount = pages;
  166. #ifdef unix
  167.                 if(isatty(fileno(stdout)))
  168.                     ttyfd = open("/dev/tty",0);
  169. #else
  170.                 ttyfd = fileno (stdout);
  171. #endif
  172.                 return;
  173.             default:
  174.                 fprintf(stderr,"Usage: %s [-d] [-efile] [-iindex] [-nN] [-sN] files\n",progname);
  175.                 exit(1);
  176.             }
  177. }
  178.  
  179. /*
  180. **    tpr - here is the main routine for each file
  181. **    the name is passed along so that the 'include' directive
  182. **    can call 'tpr' recursively
  183. */
  184. tpr(file,name)
  185.     FILE *file;
  186.     char *name;{
  187.     register char *savename;
  188.     register short saveline;
  189.     char inbuf[MAXIN];
  190.     char *ngetl();
  191.  
  192.     savename = filename;    /* save old name */
  193.     filename = name;    /* make new one available for error routine */
  194.     saveline = fileline;    /* and line number */
  195.     fileline = 0;
  196.     while(ngetl(inbuf,file) != CHARNULL){
  197.         ++fileline;
  198.         if(*inbuf == env.comchr)    /* it's a command */
  199.             cmd(inbuf,file);
  200.         else            /* it's text */
  201.             text(inbuf);
  202.         }
  203.     filename = savename;    /* restore name and linenumber */
  204.     fileline = saveline;
  205. }
  206.  
  207. /*
  208. **    error - prints filename and linenumber
  209. */
  210. error(msg,arg)
  211.     char *msg,*arg;{
  212.  
  213.     fprintf(stderr,"At line %d in file %s: ",fileline,filename);
  214.     fprintf(stderr,msg,arg);
  215. }
  216.  
  217. /*
  218. **    bold - bolden a line
  219. */
  220. bold(buf,tbuf,tend)
  221.     char *buf,*tbuf,*tend;{
  222.     register char c;
  223.     register char *p,*q;
  224.     char *strcpy();
  225.     
  226.     p = buf;
  227.     q = tbuf;
  228.     while(*p != '\n' && q < tend){
  229.         if(isprint(c = *p++)){
  230.             *q++ = c;
  231.             *q++ = '\b';
  232.             }
  233.         *q++ = c;
  234.         }
  235.     *q++ = '\n';
  236.     *q = '\0';
  237.     strcpy(buf,tbuf);    /* copy it back to buf */
  238. }
  239.  
  240. /*
  241. **    blnk - space n lines (to new page if necessary, cf spc)
  242. */
  243. blnk(n)
  244.     short n;{
  245.     register short i;
  246.     short nextline();
  247.     
  248.     linebreak();
  249.     while(n > 0){
  250.         if(lineno > env.bottom){
  251.             pfoot();
  252.             lineno = 0;
  253.             peekno = nextline(lineno);
  254.             }
  255.         if(lineno == 0)
  256.             newpage();
  257.         i = min(n,env.bottom + 1 - lineno);
  258.         skip(i);
  259.         n -= i;
  260.         lineno += i;
  261.         peekno = nextline(lineno);
  262.         }
  263.     if(lineno > env.bottom)
  264.         pfoot();
  265. }
  266.  
  267. /*
  268. **    linebreak - end current filled line
  269. */
  270. linebreak(){
  271.     
  272.     if(outp != outbuf){
  273.         *outp++ = '\n';
  274.         *outp = '\0';
  275.         put(outbuf);
  276.         }
  277.     outp = outbuf;
  278.     outw = 0;
  279.     outwds = 0;
  280. }
  281.  
  282. /*
  283. **    centre - centre a line by setting tival
  284. */
  285. center(buf)
  286.     char *buf;{
  287.     short width();
  288.     
  289.     env.tival = max((env.llval + env.tival - width(buf))/2,0);
  290. }
  291.  
  292. /*
  293. **    cmd - perform formatting command
  294. */
  295. cmd(buf,file)
  296.     char *buf;
  297.     FILE *file;{
  298.     CMDNUM comtyp();
  299.     CMDNUM ct;
  300.     register short spval,val;
  301.     register char *p;
  302.     short macnum;
  303.     char argtyp;
  304.     char fn[MAXFN];
  305.     FILE *fp;
  306.     int strlen();
  307.     short getval(),set();
  308.     char *gettl();
  309.     
  310.     if(echodir)
  311.         putdir(buf);
  312.     ct = comtyp(buf,&macnum);
  313.     val = 0;
  314.     val = getval(buf,&argtyp);
  315.     switch(ct){
  316.         case SPA:
  317.             spval = set(0,val,argtyp,1,0,HUGE);
  318.             spc(spval);
  319.             break;
  320.         case IND:
  321.         case INX:
  322.             if(ct == IND)
  323.                 linebreak();
  324.             env.inval = set(env.inval,val,argtyp,0,0,env.llval - 1);
  325.             env.tival = env.inval;
  326.             break;
  327.         case TMI:
  328.             linebreak();
  329.             env.tival = set(env.tival,val,argtyp,0,0,env.llval);
  330.             break;
  331.         case CEN:
  332.             linebreak();
  333.             env.ceval = set(env.ceval,val,argtyp,1,0,HUGE);
  334.             break;
  335.         case UDL:
  336.             env.ulval = set(env.ulval,val,argtyp,0,1,HUGE);
  337.             break;
  338.         case BLD:
  339.             env.bdval = set(env.bdval,val,argtyp,0,1,HUGE);
  340.             break;
  341.         case FIL:
  342.             linebreak();
  343.             env.fill = YES;
  344.             break;
  345.         case NFL:
  346.             linebreak();
  347.             env.fill = NO;
  348.             break;
  349.         case BRE:
  350.             linebreak();
  351.             break;
  352.         case BLN:
  353.             env.blval = set(env.blval,val,argtyp,1,0,HUGE);
  354.             blnk(env.blval);
  355.             env.blval = 0;
  356.             break;
  357.         case NED:
  358.             if(val > env.bottom - peekno + 1)
  359.                 spc(HUGE);
  360.             break;
  361.         case LNS:
  362.             env.lsval = set(env.lsval,val,argtyp,1,1,HUGE);
  363.             break;
  364.         case LNL:
  365.             env.llval = set(env.llval,val,argtyp,PAGEWIDTH,env.tival + 1,HUGE);
  366.             break;
  367.         case PGL:
  368.             env.plval = set(env.plval,val,argtyp,PAGLEN,
  369.                 env.m1val + env.m2val + env.m3val + env.m4val + 1,HUGE);
  370.             env.bottom = env.plval - env.m3val - env.m4val;
  371.             break;
  372.         case BPG:
  373.             if(lineno > 0)
  374.                 spc(HUGE);
  375.             curpag = set(curpag,val,argtyp,curpag + 1, - HUGE,HUGE);
  376.             newpag = curpag;
  377.             break;
  378.         case HED:
  379.             env.evenhdr = env.oddhdr = gettl(buf);
  380.             break;
  381.         case FOT:
  382.             env.evenftr = env.oddftr = gettl(buf);
  383.             break;
  384.         case EHD:
  385.             env.evenhdr = gettl(buf);
  386.             break;
  387.         case EFO:
  388.             env.evenftr = gettl(buf);
  389.             break;
  390.         case OHD:
  391.             env.oddhdr = gettl(buf);
  392.             break;
  393.         case OFO:
  394.             env.oddftr = gettl(buf);
  395.             break;
  396.         case NAD:
  397.             env.adjust = NO;
  398.             break;
  399.         case ADJ:
  400.             env.adjust = YES;
  401.             break;
  402.         case ROM:
  403.             env.numtyp = ROMAN;
  404.             break;
  405.         case ARA:
  406.             env.numtyp = ARABIC;
  407.             break;
  408.         case ENG:
  409.             env.numtyp = ENGLISH;
  410.             break;
  411.         case LIT:
  412.             env.litval = set(env.litval,val,argtyp,1,0,HUGE);
  413.             break;
  414.         case M1:
  415.             env.m1val = set(env.m1val,val,argtyp,M1DEF,
  416.                 0,env.plval - (env.m2val + env.m3val + env.m4val + 1));
  417.             break;
  418.         case M2:
  419.             env.m2val = set(env.m2val,val,argtyp,M2DEF,
  420.                 0,env.plval - (env.m1val + env.m3val + env.m4val + 1));
  421.             break;
  422.         case M3:
  423.             env.m3val = set(env.m3val,val,argtyp,M3DEF,
  424.                 0,env.plval - (env.m1val + env.m2val + env.m4val + 1));
  425.             env.bottom = env.plval - env.m3val - env.m4val;
  426.             break;
  427.         case M4:
  428.             env.m4val = set(env.m4val,val,argtyp,M4DEF,
  429.                 0,env.plval - (env.m1val + env.m2val + env.m3val + 1));
  430.             env.bottom = env.plval - env.m3val - env.m4val;
  431.             break;
  432.         case CMC:
  433.             if(argtyp != '\n')
  434.                 env.comchr = argtyp;
  435.             else
  436.                 env.comchr = COMMAND;
  437.             break;
  438.         case POF:
  439.             env.poval = set(env.poval,val,argtyp,0,0,PAPERSIZE);
  440.             break;
  441.         case SKP:
  442.             env.skpval = set(env.skpval,val,argtyp,1,0,HUGE);
  443.             break;
  444.         case DFN:
  445.             getmac(buf,file);
  446.             break;
  447.         case TCH:
  448.             if(argtyp != '\n')
  449.                 env.tabchr = argtyp;
  450.             else
  451.                 env.tabchr = '\t';
  452.             break;
  453.         case TCL:
  454.             tabcol(buf);
  455.             break;
  456.         case UBC:
  457.             if(argtyp != '\n')
  458.                 env.ubchr = argtyp;
  459.             else
  460.                 env.ubchr = ' ';
  461.             break;
  462.         case REF:
  463.             if(indfp != NULL)
  464.                 indline = set(indline,val,argtyp,1,0,HUGE);
  465.             break;
  466.         case RPG:
  467.             respage += set(0,val,argtyp,1,0,HUGE);
  468.             break;
  469.         case PGT:
  470.             settrap(buf);
  471.             break;
  472.         case RNV:
  473.             if(val <= 0)
  474.                 val = 1;
  475.             resenv(val);
  476.             break;
  477.         case SNV:
  478.             savenv();
  479.             break;
  480.         case MAC:
  481.             expand(macnum);
  482.             break;
  483.         case SOU:
  484.             skipnbl(buf);
  485.             skipbl(buf);
  486.             for(p = fn; p < &fn[MAXFN - 1] && *buf != '\n'; )
  487.                 *p++ = *buf++;
  488.             *p = '\0';
  489.             if((fp = fopen(fn,"r")) == NULL)
  490.                 error("Cannot open %s\n",fn);
  491.             else{
  492.                 tpr(fp,fn);
  493.                 fclose(fp);
  494.                 }
  495.             break;
  496.         case UNKNOWN:
  497.             error("Unrecognised directive:\n%s",buf);
  498.             return;
  499.         }
  500. }
  501.  
  502. /*
  503. **    comtyp - decode command type
  504. */
  505. CMDNUM comtyp(buf,macnum)
  506.     char *buf;
  507.     short *macnum;{
  508.     register char a,b;
  509.     register struct cmdents *p;
  510.     register char *q;
  511.     register short l,h,m;
  512.     
  513.     a = buf[1];
  514.     b = buf[2];
  515.     for(l = 0, h = (sizeof(builtins)/sizeof(builtins[0])) - 1; l <= h; ){
  516.         p = &builtins[m = (l + h) / 2];
  517.         if(a < p->cmdname[0] || a <= p->cmdname[0] && b < p->cmdname[1])
  518.             h = m - 1;
  519.         else if(a > p->cmdname[0] || a <= p->cmdname[0] && b > p->cmdname[1])
  520.             l = m + 1;
  521.         else
  522.             break;
  523.         }
  524.     if(l <= h && p->notredefd)
  525.         return((CMDNUM)m);
  526.     for(l = maccnt - 1; l >= 0; l--){
  527.         q = macros[l].macnam;
  528.         if(a == *q++ && b == *q){
  529.             *macnum = l;
  530.             return(MAC);
  531.             }
  532.         }
  533.     return(UNKNOWN);
  534. }
  535.  
  536. #ifdef AMIGA
  537. perror (arg)
  538. char *arg;
  539. {
  540.     if (arg && *arg) {
  541.     fprintf (stderr, "%s: ", arg);
  542.     }
  543.     fprintf (stderr, "<unknown error>\n");
  544. }
  545. #endif
  546.  
  547.